package ibm.cognos.imt;

import com.cognos.developer.schemas.bibus._3.*;
import org.apache.axis.client.Stub;
import org.apache.axis.message.SOAPHeaderElement;

import javax.xml.namespace.QName;
import javax.xml.rpc.ServiceException;
import java.net.MalformedURLException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created with IntelliJ IDEA.
 * User: eric
 * Date: 2/26/14
 * Time: 5:24 PM
 * To change this template use File | Settings | File Templates.
 */
public class CMServiceUtil {

    private static ContentManagerService_PortType cmService = null;

//    public CMServiceUtil() {
//        try {
//            connectToReportServer();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }

    private static ContentManagerService_PortType getCmService() throws Exception {
        if (cmService == null) {
            connectToReportServer();
        }
        return cmService;
    }

    public static void connectToReportServer() throws Exception {
        ContentManagerService_ServiceLocator cmServiceLocator = new ContentManagerService_ServiceLocator();
        System.out.println("connect to server "+endPoint());
        cmService = cmServiceLocator.getcontentManagerService(new java.net.URL(endPoint()));
    }

    public void logon(String namespace, String uid, String pwd) throws Exception {
        StringBuffer credentialXML = new StringBuffer();

        credentialXML.append("<credential>");
        credentialXML.append("<namespace>").append(namespace).append("</namespace>");
        credentialXML.append("<username>").append(uid).append("</username>");
        credentialXML.append("<password>").append(pwd).append("</password>");
        credentialXML.append("</credential>");

        String encodedCredentials = credentialXML.toString();

        try {
            cmService.logon(new XmlEncodedXML(encodedCredentials), null);

            SOAPHeaderElement temp = ((Stub) cmService).getResponseHeader
                    ("http://developer.cognos.com/schemas/bibus/3/", "biBusHeader");
            BiBusHeader cmBiBusHeader = (BiBusHeader) temp.getValueAsType
                    (new QName("http://developer.cognos.com/schemas/bibus/3/", "biBusHeader"));
            ((Stub) cmService).setHeader
                    ("http://developer.cognos.com/schemas/bibus/3/", "biBusHeader", cmBiBusHeader);

        } catch (Exception ex) {
            System.out.println("exception thrown " + ex);
            return;
        }
        System.out.println("Logon successful as " + uid);
    }

    public void getModel(String packageSearchPath, int i) throws Exception {
        PropEnum props[] = new PropEnum[]{PropEnum.searchPath, PropEnum.model};

        BaseClass[] model = getCmService().query(new SearchPathMultipleObject(packageSearchPath + "/model"), props, new Sort[]{}, new QueryOptions());

        System.out.println(model.length);

//        for(int i = 0; i < model.length; i++)
//        {
        System.out.println("\n**********************************************************\n");
        System.out.println("Model: " + model[i].getSearchPath().getValue() + "\n");
        System.out.println(((Model) model[i]).getModel().getSchemaInfo());
        System.out.println("\n**********************************************************\n");

        //If you want to write the model data to a file that can be opened from Framework Manager,
        //Uncomment the following lines

        /*String modelFile="d:\\temp\\model"+i+".xml";
        File oFile = new File(modelFile);
        FileOutputStream fos = new FileOutputStream(oFile);
        String temp=((Model)model[i]).getModel().getValue();
        ByteArrayInputStream bais = new ByteArrayInputStream(temp.getBytes("UTF-8"));
        System.out.println("Writing model data to file "+modelFile);
        while (bais.available() > 0) {
                fos.write(bais.read());
            };
        fos.flush();
        fos.close();*/

//        }
    }

    public List<String> getAllReportNames() throws Exception, ServiceException {
        {
            ContentManagerService_ServiceLocator contentManagerServiceLocator = null;
            contentManagerServiceLocator = new ContentManagerService_ServiceLocator();

            List<String> output = new ArrayList<String>();
            java.net.URL serverURL = new java.net.URL(endPoint());
            cmService = contentManagerServiceLocator.getcontentManagerService(serverURL);

            PropEnum props[] = new PropEnum[]{PropEnum.searchPath, PropEnum.defaultName, PropEnum.metadataModel, PropEnum.metadataModelPackage};

            // set the QueryOptions referenceProps option

            PropEnum referenceProps[] = new PropEnum[]{PropEnum.defaultName, PropEnum.searchPath, PropEnum.version};

            RefProp refPropArray[] = {new RefProp()};
            refPropArray[0].setProperties(referenceProps);
            refPropArray[0].setRefPropName(PropEnum.metadataModelPackage);

            QueryOptions qops = new QueryOptions();
            qops.setRefProps(refPropArray);

            Sort sortOptions[] = {new Sort()};
            sortOptions[0].setOrder(OrderEnum.ascending);
            sortOptions[0].setPropName(PropEnum.defaultName);
            BaseClass bc[] = getCmService().query(new SearchPathMultipleObject("//report"), props, sortOptions, qops);
//            output = output.concat("Reports:\n\n");

            for (int i = 0; i < bc.length; i++) {
                BaseClassArrayProp pkg = ((AuthoredReport) bc[i]).getMetadataModelPackage();
                String packageName = "Package name not available";
                String packageSearchPath = "Package Search Path not available";
                if (pkg.getValue() != null) {
                    packageName = ((AuthoredReport) bc[i]).getMetadataModelPackage().getValue()[0].getDefaultName().getValue();
                    packageSearchPath = ((AuthoredReport) bc[i]).getMetadataModelPackage().getValue()[0].getSearchPath().getValue();
                }

                // Statement to only get the information of a desired package from the content store.
                // compare "packname" variable declared at start with the packageName found for report.

                System.out.println(packageName + " -> " + bc[i].getDefaultName().getValue());
                String reportName = bc[i].getDefaultName().getValue();
                String reportSearchPath = bc[i].getSearchPath().getValue();
                output.add(reportSearchPath);
            }

            System.out.println(output.size());
            return output;
        }
    }

    public String getReportNames(String packname) throws Exception {
        ContentManagerService_ServiceLocator contentManagerServiceLocator = null;
//        ContentManagerService_PortType cmService = null;
        String CMS_URL = "http://9.119.141.168:9300/p2pd/servlet/dispatch";
        contentManagerServiceLocator = new ContentManagerService_ServiceLocator();

        String output = "";
        java.net.URL serverURL = new java.net.URL(CMS_URL);
        cmService = contentManagerServiceLocator.getcontentManagerService(serverURL);

        PropEnum props[] = new PropEnum[]{PropEnum.searchPath, PropEnum.defaultName, PropEnum.metadataModel, PropEnum.metadataModelPackage};

        // set the QueryOptions referenceProps option

        PropEnum referenceProps[] = new PropEnum[]{PropEnum.defaultName, PropEnum.searchPath, PropEnum.version};

        RefProp refPropArray[] = {new RefProp()};
        refPropArray[0].setProperties(referenceProps);
        refPropArray[0].setRefPropName(PropEnum.metadataModelPackage);

        QueryOptions qops = new QueryOptions();
        qops.setRefProps(refPropArray);

        Sort sortOptions[] = {new Sort()};
        sortOptions[0].setOrder(OrderEnum.ascending);
        sortOptions[0].setPropName(PropEnum.defaultName);
        BaseClass bc[] = getCmService().query(new SearchPathMultipleObject("//report"), props, sortOptions, qops);
        if (bc.length > 0) {
//            output = output.concat("Reports:\n\n");

            for (int i = 0; i < bc.length; i++) {
                BaseClassArrayProp pkg = ((AuthoredReport) bc[i]).getMetadataModelPackage();
                String packageName = "Package name not available";
                String packageSearchPath = "Package Search Path not available";
                if (pkg.getValue() != null) {
                    packageName = ((AuthoredReport) bc[i]).getMetadataModelPackage().getValue()[0].getDefaultName().getValue();
                    packageSearchPath = ((AuthoredReport) bc[i]).getMetadataModelPackage().getValue()[0].getSearchPath().getValue();
                }

                // Statement to only get the information of a desired package from the content store.
                // compare "packname" variable declared at start with the packageName found for report.

                System.out.println(packageName + " -> " + bc[i].getDefaultName().getValue());

                if (packageName != null && packageName != "" && packageName.compareToIgnoreCase(packname) == 0)
                // Statement to do all packages and reports :
                // if (packageName != null && packageName != "")
                {
                    String reportName = bc[i].getDefaultName().getValue();
                    String reportSearchPath = bc[i].getSearchPath().getValue();
                    output = output.concat("\t\t" + reportName + "\n" +
                            "Report SearchPath:      "
                            + reportSearchPath + "\nPackage Name:\t\t" + packageName + "\n" + "Package Search Path:\t"
                            + packageSearchPath + "\n");
//                    output = output.concat(getReportSpec(reportName, reportSearchPath));
                }
            }
        } else {
            output = output.concat("There are currently no reports to view.\n");
        }

        System.out.println(output);
        return output;
    }

    public String getReportSpec(String reportFullPath) {
        Pattern pattern = Pattern.compile("(.*)\\/report\\[@name=\\'(.*)\\'\\]");
        Matcher matcher = pattern.matcher(reportFullPath);
//        if (matcher.find()) {
        matcher.find();
            String reportPath = matcher.group(1)+"/report";
            String reportName = matcher.group(2);
        System.out.println(reportName + ":" + reportPath) ;

//        }
//        String reportName = report;
//        String reportPath = report;

        PropEnum props[] = new PropEnum[]{PropEnum.searchPath, PropEnum.defaultName,
                PropEnum.specification};
        String sReportSpec = "";
        try {
            BaseClass[] repPth = getCmService().query(new SearchPathMultipleObject(reportPath), props, new Sort[]{}, new QueryOptions());
            for (int i = 0; i < repPth.length; i++) {
                Report report = (Report) repPth[i];
//                System.out.println(report);
                if (reportName.equals(report.getDefaultName().getValue())) {
                    sReportSpec += (((Report) repPth[i]).getSpecification().getValue());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
//        System.out.println(sReportSpec);
        return sReportSpec;
    }

    public static void main(String[] args) {
//        getModel("http://9.119.141.168:9300/p2pd/servlet/dispatch", "/content/package[@name='p1']", 2);

        try {
            CMServiceUtil util = new CMServiceUtil();
            util.getAllReportNames();
//            util.getReportNames("GO Operational (query)");
//            util.getReportSpec("samplePie", "/content/package[@name='GO Operational (query)']/report");


            util.getReportSpec("/content/folder[@name='B5170_Solutions']/folder[@name='13 - Create a Baseline Project']/report[@name='Demo 1']");

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (ServiceException e) {
            e.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static String endPoint() {
//        return "http://192.168.1.6:9300/p2pd/servlet/dispatch";
        return BiServerConfig.dispatcherURI();
//        String url =  BiServerConfig.dispatcherURI();
//        System.out.println(url);
//        return url;
    }

    public static void getModel(String serverUrl, String packagePath, int index) {
        // connection to the Cognos service
//        String endPoint = "http://9.119.141.168:9300/p2pd/servlet/dispatch";
        // log in as a System Administrator to ensure you have the necessary permissions to access the model
        String nameSpaceID = "nameSpaceID";
        String userName = "userName";
        String password = "password";
        // search path of the package from which the model will be extracted
//        String packageSearchPath = "/content/folder[@name='Samples']/folder[@name='Models']/package[@name='GO Sales (query)']";
        String packageSearchPath = "/content/package[@name='p1']";
        CMServiceUtil test = new CMServiceUtil();

        try {
//            test.logon(nameSpaceID, userName, password);
            test.getModel(packageSearchPath, index);
            System.out.println("\nDone.");
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}
